package com.seguriapp.entities;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Reflection {

  private static Object[] GETTER_PARAM_INSTANCES = new Object[0];

  @SuppressWarnings("rawtypes")
  public static void validateEncapsulation(Class classType) throws Exception {
    Object instance;
    try {
      instance = classType.newInstance();
      testGettersAndSetters(instance);
    } catch (Exception e) {
      e.printStackTrace();
      throw e;
    }
  }

  private static void testGettersAndSetters(Object instance) {
    try {
      Method getter;
      Method setter;
      Field fields[] = instance.getClass().getDeclaredFields();

      for (Field field : fields) {
        Object value = null;
        getter = getGetter(instance.getClass(), field.getName(), field.getType());
        if (getter != null) {
          try {
            value = getter.invoke(instance, GETTER_PARAM_INSTANCES);
          } catch (Exception e) {
            System.out.println("An error ocurred in testGetSetMethods-get:" + e.getMessage());
          }
        }
        setter = getSetter(instance.getClass(), field.getName(), field.getType());
        if (setter != null) {
          try {
            setter.invoke(instance, new Object[] { value });
          } catch (Exception e) {
            System.out.println("An error ocurred in testGetSetMethods-set:" + e.getMessage());
          }
        }
      }
    } catch (Exception e) {
      return;
    }
  }

  @SuppressWarnings({ "unchecked", "rawtypes" })
  private static Method getGetter(Class classType, String field, Class type) {
    String pre = (type == boolean.class) ? "is" : "get";
    String getterName = pre + field.substring(0, 1).toUpperCase() + field.substring(1);
    Method getter;
    try {
      getter = classType.getMethod(getterName, new Class[0]);
    } catch (Exception e) {
      getter = null;
    }
    return getter;
  }

  @SuppressWarnings({ "rawtypes", "unchecked" })
  private static Method getSetter(Class classType, String field, Class type) {
    String setterName = "set" + field.substring(0, 1).toUpperCase() + field.substring(1);
    Method setter;
    try {
      setter = classType.getMethod(setterName, new Class[] { type });
    } catch (Exception e) {
      setter = null;
    }
    return setter;
  }
}
